/***************************************************************************************************
  *Copyright(C),2010-2016,Sumscope
  *FileName	:  system_time.cpp
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2016/02/01
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
  ***************************************************************************************************/
#include <time.h>
#include "system_time.h"

#ifndef WIN32
#include <sys/time.h>
#include <time.h>
#endif

//#include <atltime.h>

#define BASSERT //

namespace qb{
	namespace base{
		namespace{
			const int maxTimeBufferSize = 128;
		}
		static void AtlThrow(int i){}
		CTimeSpan::CTimeSpan() throw() :
			m_timeSpan(0)
		{
		}

		CTimeSpan::CTimeSpan(__time64_t time) throw() :
			m_timeSpan(time)
		{
		}

		CTimeSpan::CTimeSpan(LONG lDays, int nHours, int nMins, int nSecs) throw()
		{
			m_timeSpan = nSecs + 60 * (nMins + 60 * (nHours + int64_t(24) * lDays));
		}

		LONGLONG CTimeSpan::GetDays() const throw()
		{
			return(m_timeSpan / (24 * 3600));
		}

		LONGLONG CTimeSpan::GetTotalHours() const throw()
		{
			return(m_timeSpan / 3600);
		}

		LONG CTimeSpan::GetHours() const throw()
		{
			return(LONG(GetTotalHours() - (GetDays() * 24)));
		}

		LONGLONG CTimeSpan::GetTotalMinutes() const throw()
		{
			return(m_timeSpan / 60);
		}

		LONG CTimeSpan::GetMinutes() const throw()
		{
			return(LONG(GetTotalMinutes() - (GetTotalHours() * 60)));
		}

		LONGLONG CTimeSpan::GetTotalSeconds() const throw()
		{
			return(m_timeSpan);
		}

		LONG CTimeSpan::GetSeconds() const throw()
		{
			return(LONG(GetTotalSeconds() - (GetTotalMinutes() * 60)));
		}

		__time64_t CTimeSpan::GetTimeSpan() const throw()
		{
			return(m_timeSpan);
		}

		CTimeSpan CTimeSpan::operator+(CTimeSpan span) const throw()
		{
			return(CTimeSpan(m_timeSpan + span.m_timeSpan));
		}

		CTimeSpan CTimeSpan::operator-(CTimeSpan span) const throw()
		{
			return(CTimeSpan(m_timeSpan - span.m_timeSpan));
		}

		CTimeSpan& CTimeSpan::operator+=(CTimeSpan span) throw()
		{
			m_timeSpan += span.m_timeSpan;
			return(*this);
		}

		CTimeSpan& CTimeSpan::operator-=(CTimeSpan span) throw()
		{
			m_timeSpan -= span.m_timeSpan;
			return(*this);
		}

		bool CTimeSpan::operator==(CTimeSpan span) const throw()
		{
			return(m_timeSpan == span.m_timeSpan);
		}

		bool CTimeSpan::operator!=(CTimeSpan span) const throw()
		{
			return(m_timeSpan != span.m_timeSpan);
		}

		bool CTimeSpan::operator<(CTimeSpan span) const throw()
		{
			return(m_timeSpan < span.m_timeSpan);
		}

		bool CTimeSpan::operator>(CTimeSpan span) const throw()
		{
			return(m_timeSpan > span.m_timeSpan);
		}

		bool CTimeSpan::operator<=(CTimeSpan span) const throw()
		{
			return(m_timeSpan <= span.m_timeSpan);
		}

		bool CTimeSpan::operator>=(CTimeSpan span) const throw()
		{
			return(m_timeSpan >= span.m_timeSpan);
		}
		////////////////////////////////////////////////////////////////////////////////
		CTime::CTime() throw() :
			m_time(0)
		{
		}

		CTime::CTime(__time64_t time)  throw() :
			m_time(time)
		{
		}

		CTime::CTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec,
			int nDST)
		{
#pragma warning (push)
#pragma warning (disable: 4127)  // conditional expression constant

			BASSERT(nYear >= 1900);
			BASSERT(nMonth >= 1 && nMonth <= 12);
			BASSERT(nDay >= 1 && nDay <= 31);
			BASSERT(nHour >= 0 && nHour <= 23);
			BASSERT(nMin >= 0 && nMin <= 59);
			BASSERT(nSec >= 0 && nSec <= 59);

#pragma warning (pop)

			struct tm atm;

			atm.tm_sec = nSec;
			atm.tm_min = nMin;
			atm.tm_hour = nHour;
			atm.tm_mday = nDay;
			atm.tm_mon = nMonth - 1;        // tm_mon is 0 based
			atm.tm_year = nYear - 1900;     // tm_year is 1900 based
			atm.tm_isdst = nDST;

#ifndef WIN32
			m_time = mktime(&atm);
#else
			m_time = _mktime64(&atm);
#endif
			BASSERT(m_time != -1);       // indicates an illegal input time
		}

		CTime::CTime(WORD wDosDate, WORD wDosTime, int nDST)
		{
			struct tm atm;
			atm.tm_sec = (wDosTime & ~0xFFE0) << 1;
			atm.tm_min = (wDosTime & ~0xF800) >> 5;
			atm.tm_hour = wDosTime >> 11;

			atm.tm_mday = wDosDate & ~0xFFE0;
			atm.tm_mon = ((wDosDate & ~0xFE00) >> 5) - 1;
			atm.tm_year = (wDosDate >> 9) + 80;
			atm.tm_isdst = nDST;
#ifndef WIN32
			m_time = mktime(&atm);
#else
			m_time = _mktime64(&atm);
#endif
			BASSERT(m_time != -1);       // indicates an illegal input time
		}

		CTime& CTime::operator=(__time64_t time) throw()
		{
			m_time = time;

			return(*this);
		}

		CTime& CTime::operator+=(CTimeSpan span) throw()
		{
			m_time += span.GetTimeSpan();

			return(*this);
		}

		CTime& CTime::operator-=(CTimeSpan span) throw()
		{
			m_time -= span.GetTimeSpan();

			return(*this);
		}

		CTimeSpan CTime::operator-(CTime time) const throw()
		{
			return(CTimeSpan(m_time - time.m_time));
		}

		CTime CTime::operator-(CTimeSpan span) const throw()
		{
			return(CTime(m_time - span.GetTimeSpan()));
		}

		CTime CTime::operator+(CTimeSpan span) const throw()
		{
			return(CTime(m_time + span.GetTimeSpan()));
		}

		bool CTime::operator==(CTime time) const throw()
		{
			return(m_time == time.m_time);
		}

		bool CTime::operator!=(CTime time) const throw()
		{
			return(m_time != time.m_time);
		}

		bool CTime::operator<(CTime time) const throw()
		{
			return(m_time < time.m_time);
		}

		bool CTime::operator>(CTime time) const throw()
		{
			return(m_time > time.m_time);
		}

		bool CTime::operator<=(CTime time) const throw()
		{
			return(m_time <= time.m_time);
		}

		bool CTime::operator>=(CTime time) const throw()
		{
			return(m_time >= time.m_time);
		}

		struct tm* CTime::GetGmtTm(struct tm* ptm) const
		{
			// Ensure ptm is valid
			BASSERT(ptm != NULL);

			if (ptm != NULL)
			{
				struct tm ptmTemp;
#ifdef WIN32
				errno_t err = _gmtime64_s(&ptmTemp, &m_time);
#else
				int err = 0;
				struct tm* pTime = &ptmTemp;
				pTime = gmtime(&m_time);
#endif

				// Be sure the call succeeded
				if (err != 0) { return NULL; }

				*ptm = ptmTemp;
				return ptm;
			}

			return NULL;
		}

		struct tm* CTime::GetLocalTm(struct tm* ptm) const
		{
			// Ensure ptm is valid
			BASSERT(ptm != NULL);

			if (ptm != NULL)
			{
				struct tm ptmTemp;
				int err = 0;
#if WIN32
				err = _localtime64_s(&ptmTemp, &m_time);
#else
				ptmTemp = *localtime(&m_time);
#endif

				if (err != 0)
				{
					return NULL;    // indicates that m_time was not initialized!
				}

				*ptm = ptmTemp;
				return ptm;
			}

			return NULL;
		}

		__time64_t CTime::GetTime() const throw()
		{
			return(m_time);
		}

		int CTime::GetYear() const
		{
			struct tm ttm;
			struct tm * ptm;

			ptm = GetLocalTm(&ttm);
			return ptm ? (ptm->tm_year) + 1900 : 0;
		}

		int CTime::GetMonth() const
		{
			struct tm ttm;
			struct tm * ptm;

			ptm = GetLocalTm(&ttm);
			return ptm ? ptm->tm_mon + 1 : 0;
		}

		int CTime::GetDay() const
		{
			struct tm ttm;
			struct tm * ptm;

			ptm = GetLocalTm(&ttm);
			return ptm ? ptm->tm_mday : 0;
		}

		int CTime::GetHour() const
		{
			struct tm ttm;
			struct tm * ptm;

			ptm = GetLocalTm(&ttm);
			return ptm ? ptm->tm_hour : -1;
		}

		int CTime::GetMinute() const
		{
			struct tm ttm;
			struct tm * ptm;

			ptm = GetLocalTm(&ttm);
			return ptm ? ptm->tm_min : -1;
		}

		int CTime::GetSecond() const
		{
			struct tm ttm;
			struct tm * ptm;

			ptm = GetLocalTm(&ttm);
			return ptm ? ptm->tm_sec : -1;
		}

		int CTime::GetDayOfWeek() const
		{
			struct tm ttm;
			struct tm * ptm;

			ptm = GetLocalTm(&ttm);
			return ptm ? ptm->tm_wday + 1 : 0;
		}

		//WideString CTime::Format(LPCTSTR pFormat) const
		//{
		//	if (pFormat == NULL)
		//	{
		//		return pFormat;
		//	}

		//	TCHAR szBuffer[maxTimeBufferSize] = { 0 };
		//	struct tm ptmTemp;

		//	if (_localtime64_s(&ptmTemp, &m_time) != 0)
		//	{
		//		AtlThrow(E_INVALIDARG);
		//	}

		//	if (!wcsftime(szBuffer, maxTimeBufferSize, pFormat, &ptmTemp))
		//	{
		//		szBuffer[0] = '\0';
		//	}

		//	return szBuffer;
		//}

	}//namespace base;
}//namespace ss;